Projet Zuul de conception orientée objet en Java d'un jeu d'aventure
Forum des exercices du projet Zuul
Exercice 7.18.8
Ajouter au moins un bouton qui déclenche une des commandes du jeu.
Attention ! Les commandes doivent toujours pouvoir être tapées dans la ligne de saisie.
Vous pouvez vous aider des liens présents dans la rubrique Plus de technique.
Aide pour comprendre l'ajout d'un bouton
- Observez les classes utilisées dans UserInterface pour créer divers composants : JTextField,
JTextArea, JLabel, JScrollPane, JPanel,
JFrame, ... Il ne doit pas être bien difficile de trouver sur internet quelle classe peut servir pour créer un bouton.
- Si vous voulez qu'un texte précis apparaisse sur ce bouton, il faut probablement le préciser à la création de l'objet.
- Si vous observez où sont placés les 3 composants existants (image, listScroller,
entryField), vous constaterez qu'il ne reste que 2 places libres pour votre bouton ; choisissez-en une !
(on ne veut pas positionner les boutons au pixel près, les 5 positions prédéfinies suffisent)
Compilez, testez pour voir si le bouton apparaît bien où vous le souhaitiez.
Cliquez dessus ; il ne se passe rien ? C'est normal, voir pour cela les 2 points suivants. - Dans la partie // add some event listeners to some components
on ne s'intéresse qu'à l'entryField, pour savoir quand on a tapé ENTRÉE à la fin de la ligne.
Il faut donc maintenant de la même façon ajouter un "écouteur d'action" sur notre bouton.
Le paramètre this signifie ici que c'est l'objet courant qui réagira à l'évènement (touche ENTRÉE ou clic sur le bouton). - Pour l'instant, la méthode actionPerformed (automatiquement appelée en cas d'évènement sur un des composants bénéficiant d'un "écouteur d'action")
appelle systématiquement processCommand qui traite la ligne de commande tapée par le joueur (dans l'entryField). Il nous faut donc auparavant tester si l'évènement ne serait pas plutôt un clic sur le bouton,
et dans ce cas, déclencher l'action correspondante. Pour cela, 2 possibilités :
- utilisez la fonction getActionCommand qui retourne la String correspondant au texte figurant sur le bouton (si on a cliqué sur un bouton)
- utilisez la fonction getSource qui retourne la référence vers le composant qui a généré l'évènement
Ne pas oublier que s'il y a un évènement alors qu'on n'a pas cliqué sur un bouton, c'est qu'on a tapé quelque chose dans l'entryField !
Vous pouvez aussi lire les explications sur ActionListener et les classes anonymes
Lorsque vous dites que le bouton doit déclencher la commande, cela veut-il dire que la commande doit-être exécutée ou bien être inscrite dans le parser?
Il faut demander au GameEngine d'exécuter directement la commande "xxx" correspondant à ce qui est indiqué sur le bouton (remplace le fait de taper "xxx" dans la zone de saisie de texte).
Je ne vois pas comment je peux faire car la classe GameEngine ne possède qu'une méthode qui a une String en paramètre et celle ci ne peux pas être utilisé ...
Je suis bloqué ici :
if(e.getSource() == bouton)
{
this.engine.Uneclasse("go bas");
}
Je ne sais pas quoi mettre a la place de Uneclasse pour que bouton execute directement la string " go bas".
Merci d'avance
Je ne comprends pas bien votre message :
Si GameEngine possède une méthode void m(String p) qui permet d'exécuter une commande, pourquoi ne pas écrire this.aEngine.m("go bas"); ?
Car la seule méthode avec une string en paramètre qui se trouve dans la classe GameEngine est celle ci :
public void interpretCommand(String Commandline)
{
code supprimé pour ne pas influencer les futurs lecteurs
}
Je ne vois pas comment je peux provoquer le changement de salle avec cette methode.
(Modifié par Denis BUREAU. Écrit initialement le dimanche 13 octobre 2013, 23:02)
Si la méthode est : interpretCommand(String Commandline)
c'est qu'elle est capable d'interpréter (exécuter) la commande passée en paramètre (commandLine = ligne de commande) !
Il suffit de regarder ses instructions pour y trouver :
if(CommandWord.equals("go"))
{
goRoom(vCommand);
}
Pourquoi cela ne provoquerait-il pas le changement de salle ?
P.S.: votre méthode n'est pas bien programmée puisqu'on y trouve une suite de if non indépendants sans else :
si vous savez que la commande est "xxx" (et que vous l'avez exécutée), à quoi cela sert-il de vérifier ensuite si elle est "yyy" ? Ce n'est que si elle n'est pas "xxx" qu'il faut vérifier si elle est "yyy" !
Un étudiant a écrit :
Un étudiant a écrit :
Bonjour,
J'ai un nouveau warning dans ma classe UserInterface :
enable(boolean) in java.awt.Component has been deprecated
Je ne trouve pas ce qu'il signifie, que faire ??
Merci d'avance !
On crée le bouton dans la classe interface ou bien on doit créer une nouvelle classe spécifique?
Où sont placés les 3 composants graphiques existants (image, listScroller, entryField) ?
Le bouton est juste un composant graphique supplémentaire.
Je n'arrive pas à trouver ce qu'il faut tester pour pouvoir savoir si on a cliqué sur un bouton ou si on a entré une chaîne de caractère dans l'entryField. Pouvez-vous m'aider? voici mon code
public void actionPerformed(ActionEvent e)
{ if ( e = aentryField )
aengine.interpretCommand(e.getActionCommand());
else if (e != aentryField )
{ processCommand();}
}
La logique serait plutôt :
SI on a cliqué sur le boutonA
ALORS exécuter la commande1
SINON SI on a cliqué sur le boutonB
ALORS exécuter la commande2
SINON exécuter la commande tapée dans l'entryfield
Et pour savoir si on a cliqué sur un bouton, vous pouvez choisir un des deux moyens indiqués au point 5.
C'est effectivement peu naturel d'écrire ce qui est en rouge (mais c'est quand-même possible : SI la classe du composant qui a déclenché l'évènement est JButton ALORS ...).
Vous pourriez par contre écrire :
SI l'évènement provient de l'entryFieldALORS exécuter la commande tapée dans l'entryField
SINON exécuter la commande correspondant au texte sur le bouton cliqué
L'étudiant a répondu :
En fait, comment récupérer ce dont provient l'évènement ?
Vous avez bien compris que e.getClass() renvoyait la classe de l'évènement (ActionEvent).
Au passage, je vous signale que vous disposez déjà d'au moins une variable JButton vous permettant d'écrire monBouton.getClass() si vous avez appelé monBouton le bouton que vous avez créé.
Pour répondre à votre dernière question, il vous suffit de relire attentivement le point 5 de l'énoncé, notamment la 2ème solution présentée.
Un étudiant a écrit :
Je n'arrive pas à trouver mon erreur, pouvez vous me venir en aide s'il vous plait ?
Merci d'avance
Le sage a dit : "Si l'homme pauvre a faim, ne lui donne pas un poisson, apprends-lui à pêcher."
Donc, plutôt que de vous donner la solution, je préfère vous apprendre à la trouver par vous-même :
- prendre les éléments dans le message d'erreur :
il s'agit de la méthode enable (avec un paramètre boolean) dans la classe Component (du paquetage java.awt) - chercher cette méthode dans la javadoc de cette classe
(taper java 7 component dans google, puis chercher enable dans la page) - il est bien indiqué que la méthode enable est deprecated (obsolète)et il est précisé la méthode qu'on doit utiliser à la place (chercher cette méthode dans la page)
- effectuer la modification dans son code, compiler, tester
Bonjour,
Suite
à de nombreuses modifications, je me suis rendu compte que j'ai des
actions qui était réalisé deux fois. Etant surpris j'ai fais une debug
et je me suis appercu que l'événement d'appuie sur un bouton était
doublon. L'appui d'une seule fois sur le bouton est détecté deux fois
par mon jeu.
Je ne comprends pas d'où vient le problème.
Nous
avons éssayé de comprendre d'où venait le problème la semaine dernière
avec monsieur Kachouri mais ce fu sans réussite. Avez-vous déjà croisé
ce type de problème et savez vous le résoudre ?
Si tous les boutons utilisent la même méthode actionPerformed, envoyez-moi le code de cette méthode.
public void actionPerformed(ActionEvent pE)
{
code supprimé pour ne pas influencer les futurs lecteurs
}
Je peux vous envoyer mon fichier de jeu .jar si vous le voulez.
(Modifié par Denis BUREAU. Écrit initialement le lundi 12 mai 2014, 23:18)
Bonjour,
Dans l' Exercice 7.18.6, vous écrivez que " Le Parser a changé et n'a plus besoin de Scanner", et vous écrivez ici que " Les commandes doivent toujours pouvoir être tapées dans la ligne de saisie."
Mais
si le Parser n'utilise plus le scanner pour lire ce qu'on écrit, et si
on applique les nombreux changements que l'on trouve dans
"zuul_with_images" on n'a plus accès au commandes par clavier.
Merci de m'éclairer si je n'ai pas compris quelque chose.
A partir de la version zuul-with-images, les commandes ne sont plus lues au clavier dans le Parser par un Scanner(System.in) mais dans la UserInterface par un JTextField (dont la String ainsi récupérée est envoyée au Parser pour analyse).
De façon générale, quand on vous donne une nouvelle version du jeu,
celle-ci ne remplace pas votre propre jeu ; elle vous permet de voir
comment est implémenté telle ou telle fonctionnalité. Vous devez donc
modifier votre jeu pour incorporer cette nouvelle
fonctionnalité, mais en faisant bien attention de ne pas "régresser",
c'est-à-dire remettre en cause des acquis (avantages) des exercices
précédents.
Bonjour, J'ai deux questions concernant les boutons.
Après
avoir créé mes boutons, j'ai testé mon jeu. Lorsque je clique sur le
bouton "Quit", certes, je ne peux plus rien écrire pour donner les
instructions, mais tous les boutons continuent de fonctionner... je peux donc continuer de jouer en utilisant seulement les boutons, mais ne peux plus rien écrire...
Je
pense bien qu'il faudrait désactiver les ActionListener une fois que le
joueur à cliqué sur le bouton "quit", mais je ne vois pas vraiment
comment.
Deuxième question, Dans certaines pièces, j'aimerai
désactiver certains bouton (par exemple dans la pièce "Salle de Bain",
le bouton "Eat" n'est pas vraiment indispensable.) Y a t-il un moyen de
le faire à notre niveau ?
Je pense que cette méthode répond à vos deux questions :
http://docs.oracle.com/javase/7/docs/api/java/awt/Component.html#setEnabled%28boolean%29
Dans UserInterface, j'ai initialisé le bouton.
private JButton buttonlook ;
Puis dans
createGUI() j'ai par exemple fait
Buttonlook =new JButton ("look") ;
J'ai aussi créé un JPanel pour y ajouter plusieurs boutons et
j'ai ajoutésetPreferredSize() pour la taille, ça compile mais aucune
trace du bouton.
Bonjour,
Je suis actuellement bloqué au même problème...
Par rapport à l'aide que vous nous fournissez:
1. Je pense avoir bien compris qu'il fallait bien placer le Jbutton dans la procédure createGUI() mais je ne vois pas comment le faire apparaître sur l'écran.
2. Je pense aussi avoir compris qu'écrire, par exemple , new JButton("North") permet
d'afficher "North" sur le bouton. De plus, avec les liens que vous nous
donnez, on peut ajouter une image au bouton si on rajoute une
variable, dans laquelle est stockée une image.
Donc voici ce que je comprends en résumé pour JButton() :
JButton("Nom_du_bouton" , image)
3. Concernant les 3 emplacements des composants, par rapport à l'affiche de zuul-with-image voici ce que j'ai compris:
image : Partie du haut avec l'image ;
listScroller : Partie du milieu avec le texte du jeu ;
entryField : Partie du bas avec l'invite de commande de l'utilisateur ;
Je pense qu'il faut mettre les boutons soit au niveau de l'image, soit de l'invite de commande.
Mais malgré cela, je ne vois pas comment le faire "apparaître" dans l'une des ces emplacements...
(Pour les points 4 à 6, je n'ai pas encore cherché à comprendre vu que je suis bloqué avec l'affichage du bouton)
Votre problème se situe effectivement au 3) : regardez les paramètres de l'appel de la méthode add pour les 3 composants graphiques existants, déduisez-en les 2 possibilités restantes autour du centre, et utilisez l'une d'elles pour placer votre bouton.
Merci beaucoup, j'ai bien réussi à afficher un bouton sur l'écran.
Par contre, lorsque j'essaye d'en afficher un deuxième, celui-ci remplace le premier...
Y-a-t-il une méthode ou une astuce pour éviter cette superposition de bouton ?
(Dans
mon cas, je pense plus que le 1er bouton est remplacé par le 2ème
car dans l'écriture de code, j'écris la même position pour les 2
boutons, donc lorsque la machine lit le code, celui-ci prends en compte
le deuxième et "efface" le premier.)
C'est tout à fait ça.
Pour afficher un second bouton, il suffit de le positionner dans l'emplacement opposé à celui du premier.
Pour en afficher plus, il faut créer un nouveau JPanel et l'ajouter dans un des 2 emplacements libres (lorsqu'il n'y avait aucun bouton).
Pour ne pas se restreindre au BorderLayout, regardez les documentations et tutoriels pour découvrir d'autres layouts (dispositions).
Bonsoir,
Mon problème se situe lors de l'assignation d'une commande au bouton créé. J'ai eu beau tester avec les 2 méthodes (getActionCommand et getSource), une fois le jeu lancé, je peut cliquer sur le bouton autant que je le souhaite sans que rien ne se passe. J'ai vérifié plusieurs choses et même corrigés certains problèmes qui ne s'étaient pas encore manifestés (des méthodes en private) mais impossible de faire réagir le jeu au pressage de bouton !
PS : mon code de actionPerformed
if(pE.getSource()==aBoutonLook) this.aEngine.look();
else if(pE.getSource()==aEntryField) processCommand();
Bonjour Monsieur,
- Tout d'abord, j'ai importé la classe JButton dans la classe
UserInterface qui permet de créer les composants boutons
[code supprimé pour ne pas influencer les futurs lecteurs]
- Puis, j'ai crée un panel, nommé panelBoutons, qui accueillera les boutons.
- Ensuite, j'ai ajouté le bouton boutonQuitter à ce panel grâce à
la méthode add
myFrame.getContentPane().add(panelBoutons, BorderLayout.EAST);
if (e.getSource() == entryField) {processCommand();}
Cette instruction signfie que si le composant qui a généré l'évènement est une entryField (texte entré dans l'interface textuelle ) alors on appelle la méthode processCommand().
Et j'ai rajouté l'instruction suivante pour le cas où un évènement se produit sur le bouton boutonQuitter :
if(e.getSource()==boutonQuitter) {engine.interpretCommand("quit");}
Pourriez-vous, s'il-vous-plaît, m'éclairer sur mon problème ?
1)
- "j'ai placé le panel panelBoutons à l'est de la fenêtre myFrame"
Il vaut mieux l'ajouter au panel (comme les 3 autres composants graphiques déjà présents) plutôt qu'à myFrame.
Mais ce n'est pas cela qui cause votre problème.
2)
- "Et j'ai rajouté l'instruction suivante pour le cas où un évènement se produit sur le bouton boutonQuitter"
Il ne faut pas oublier le else, car si votre bouton fonctionnait, il serait activé après l'exécution de chaque commande tapée dans l'entryField !
3)
- if(e.getSource()==boutonQuitter) {engine.interpretCommand("quit");}
Ce problème n'était pas facile à trouver, car cette ligne est habituellement correcte.
Mais comme vous avez placé votre bouton dans un JPanel, cela ne fonctionne plus.
Il vous faut donc utiliser getActionCommand() au lieu de getSource() (voir l'aide dans l'énoncé ci-dessus).
Un étudiant a écrit :
Bonsoir Monsieur Bureau,
- getActionCommand, comme son nom l'indique, est un accesseur, qui retourne une String (généralement, celle inscrite sur le bouton).
Donc, si le texte de votre bouton est "Coucou", votre code est strictement équivalent à :
if (e.getSource()== aBouton)
"Coucou";
else
processCommand();
ce qui n'exécute pas grand-chose dans le 1er cas ... - D'autre part, ce qui vous manque pour avancer est contenu dans cette phrase du point 5 de l'aide :
"Il nous faut donc maintenant tester si l'évènement ne serait pas plutôt un clic sur le bouton, et dans ce cas, déclencher l'action correspondante." - Enfin, cela peut vous être profitable de lire la plupart des échanges ci-dessus.
- Si tout ça ne suffit pas, reposez une question précise, par rapport au point où vous en serez arrivé.
Un étudiant a écrit :
D'abord, vous n'êtes pas totalement perdu puisque vous avez su déclarer et créer le bouton.
Pour la suite, effectuez point par point les 5 étapes de l'aide (en bleu) dans l'énoncé de cet exercice, et reposez une question précisément là où vous êtes bloqué.
A propos de votre dernière phrase, vous n'avez pas besoin de définir la taille du bouton (qui s'adaptera au texte que vous choisirez), mais vous devez effectivement choisir laquelle des 5 positions possibles il devra occuper (voir la documentation de la classe BorderLayout).
Un étudiant a écrit :
Puisque nous devons coder au moins un bouton, est-il possible de faire
en sorte que mon jeu ne repose que sur des boutons afin d'améliorer
l'expérience du joueur ?
Si oui, la classe Command devient obsolète non ?
Possible ? Oui. Facile ? Non. (pensez à "prendre un objet", par exemple, à partir de l'exercice 30)
Même si vous arrivez à tout faire avec des boutons, il faudra conserver la structure interne du jeu avec la classe Command, ne serait-ce que pour la commande test (à partir de l'exercice 27).
Un étudiant a écrit :
J'ai l'impression que vous n'avez pas lu attentivement l'aide fournie dans l'énoncé ci-dessus.
- "créer les boutons grâce à la classe JPanel ?"
Pensez-vous vraiment que Panel veut dire bouton en anglais ?
Avez-vous simplement essayé de taper "ajouter un bouton en java" dans Google ?
Par contre, si vous parlez de placer le bouton, il faudra effectivement le faire au sein du JPanel, à une des 2 places restantes. - "créer mon bouton Dans une nouvelle méthode ?"
Pourquoi ne voulez-vous pas créer votre bouton à l'endroit où sont créés les 3 composants existants (image, listScroller, entryField) ? - "Dans une méthode déjà existante comme actionPerformed? "
Le point 5 de l'aide explique bien que cette méthode est appelée automatiquement quand on clique sur le bouton ; ça ne semble pas être un très bon choix pour créer le bouton ...
Si tout ça ne suffit pas, posez de nouvelles questions par rapport à ce que vous aurez déjà réussi à faire.
Un étudiant a écrit :
Dans
l'exercice 7.18.8, on nous demande d'ajouter un bouton, chose faite.
J'en ai ajouté pour chaque commande, ils sont tous fonctionnels, mais
dans la zone de texte le jeu affiche d'abord "I don't know what you
mean..." puis il affiche la commande et ses sorties ou options comme prévu :
Je n'arrive pas à trouver pourquoi ce message apparaît alors qu'il exécute quand même l'action souhaitée.
1) Trouvez à quelle ligne L1 dans le code est affiché le message "I don't know what you mean...".
2) Trouvez à quelle ligne L2 dans le code est appelée la méthode qui contient la ligne L1.
3) Si un if figure dans la méthode contenant L2, voyez dans quel cas L2 est exécutée et dans quel cas elle ne l'est pas.
4) Modifiez le code pour que L2 ne soit exécutée que lorsqu'on ne clique pas sur un bouton.
Bonjour Monsieur,
J'ai bien réussi à positionner mon bouton que j'ai nommé "help".
Lorsque je clique dessus, il exécute bien printHelp.
Les autres commandes restent fonctionnelles lorsque je les saisis dans l'entry field.
Cependant,
lorsque j'écris help dans l'entry field , printHelp s'execute mais
"help" reste affiché dans l'entry field (voir pièce jointe).
Pouvez-vous me donner une piste pour résoudre ce problème s'il vous plaît ?
Réseaux sociaux